package com.itheima.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.common.domain.AjaxResult;
import com.itheima.common.constant.Constants;
import com.itheima.common.domain.PageInfo;
import com.itheima.common.utils.JwtUtil;
import com.itheima.user.entity.*;
import com.itheima.mapper.UmsAdminMapper;
import com.itheima.service.*;
import com.itheima.vo.UmsAdminRoleRelationVo;
import com.itheima.vo.UpdateAdminPasswordParamVo;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UmsAdminServiceImpl extends ServiceImpl<UmsAdminMapper, UmsAdmin> implements IUmsAdminService {
    @Autowired
    private IUmsAdminRoleRelationService iUmsAdminRoleRelationService;

    @Autowired
    private IUmsRoleService iUmsRoleService;

    @Autowired
    private IUmsRoleMenuRelationService iUmsRoleMenuRelationService;

    @Autowired
    private IUmsMenuService iUmsMenuService;

    /**
     * 修改指定用户密码
     *
     * @param updateAdminPasswordParamVo
     */
    @Override
    public void updateByUsername(UpdateAdminPasswordParamVo updateAdminPasswordParamVo) {
        LambdaUpdateWrapper<UmsAdmin> luw = new LambdaUpdateWrapper<>();
        luw.eq(updateAdminPasswordParamVo.getUsername() != null, UmsAdmin::getUsername, updateAdminPasswordParamVo.getUsername())
                .eq(updateAdminPasswordParamVo.getOldPassword() != null, UmsAdmin::getPassword, updateAdminPasswordParamVo.getOldPassword())
                .set(UmsAdmin::getPassword, updateAdminPasswordParamVo.getNewPassword());
        this.update(luw);
    }

    /**
     * 根据用户名或姓名分页获取用户列表
     *
     * @param keyword
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo getPage(String keyword, Integer pageNum, Integer pageSize) {
        Page<UmsAdmin> umsAdminPage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<UmsAdmin> lqw = new LambdaQueryWrapper<>();
        lqw.like(keyword != null, UmsAdmin::getUsername, keyword)
                .orderByAsc(UmsAdmin::getCreateTime);
        this.page(umsAdminPage, lqw);
        PageInfo pageInfo = PageInfo.toPageList(umsAdminPage);
        return pageInfo;
    }

    /**
     * 给用户分配角色
     *
     * @param
     */
    @Override
    public void roleUpdate(UmsAdminRoleRelationVo umsAdminRoleRelationVo) {
        QueryWrapper<UmsAdminRoleRelation> qw = new QueryWrapper<>();
        qw.eq("admin_id", umsAdminRoleRelationVo.getAdminId());
        iUmsAdminRoleRelationService.remove(qw);
        for (Long roleId : umsAdminRoleRelationVo.getRoleIds()) {
            UmsAdminRoleRelation umsAdminRoleRelation = new UmsAdminRoleRelation();
            umsAdminRoleRelation.setAdminId(umsAdminRoleRelationVo.getAdminId());
            umsAdminRoleRelation.setRoleId(roleId);
            iUmsAdminRoleRelationService.save(umsAdminRoleRelation);
        }
    }

    /**
     * 获取指定用户的角色
     *
     * @param adminId
     * @return
     */
    @Override
    public List<UmsRole> getRoleByAdminId(Long adminId) {
        LambdaQueryWrapper<UmsAdminRoleRelation> lqw = new LambdaQueryWrapper<>();
        lqw.eq(UmsAdminRoleRelation::getAdminId, adminId);
        List<UmsAdminRoleRelation> list = iUmsAdminRoleRelationService.list(lqw);
        return list.stream().map((umsAdminRoleRelation) -> {
            LambdaQueryWrapper<UmsRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(UmsRole::getId, umsAdminRoleRelation.getRoleId());
            return iUmsRoleService.getOne(lambdaQueryWrapper);
        }).collect(Collectors.toList());
    }

    /**
     * 登录以后返回token
     *
     * @param umsAdmin
     * @return
     */
    @Override
    public AjaxResult login(UmsAdmin umsAdmin) {
        LambdaQueryWrapper<UmsAdmin> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StringUtils.isNotEmpty(umsAdmin.getUsername()), UmsAdmin::getUsername, umsAdmin.getUsername());
        UmsAdmin user = this.getOne(lqw);

        //判断是否为空
        if (user == null) {
            return AjaxResult.error("登录失败");
        }

        //判断账号状态
        if (user.getStatus() == 0) {
            return AjaxResult.error("账户已被禁用");
        }

        //比较密码
        if (BCrypt.checkpw(umsAdmin.getPassword(), user.getPassword())) {
            Map<String, Object> map = new HashMap<>();
            map.put(Constants.USERNAME, user.getUsername());
            map.put(Constants.NICK_NAME, user.getNickName());
            String userJson = JSON.toJSONString(map);
            String token = JwtUtil.createJWT(UUID.randomUUID().toString(), userJson, null);
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put(Constants.TOKEN_HEAD, Constants.TOKEN_PREFIX);
            userInfo.put(Constants.TOKEN, token);
            return AjaxResult.success("登陆成功", userInfo);
        }
        return AjaxResult.error("用户名或密码有误");
    }

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    @Override
    public Map<String, Object> info(HttpServletRequest request) {
        String authorization = request.getHeader(Constants.AUTHORIZATION);
        String[] split = authorization.split(" ");
        try {
            Claims claims = JwtUtil.parseJWT(split[1]);
            String sub = (String) claims.get(Constants.JWT_USERNAME);
            JSONObject user = JSON.parseObject(sub);
            String username = (String) user.get(Constants.USERNAME);
            LambdaQueryWrapper<UmsAdmin> lqw = new LambdaQueryWrapper<>();
            lqw.eq(UmsAdmin::getUsername, username);
            UmsAdmin umsAdmin = this.getOne(lqw);

            LambdaQueryWrapper<UmsAdminRoleRelation> lqw1 = new LambdaQueryWrapper<>();
            lqw1.eq(UmsAdminRoleRelation::getAdminId, umsAdmin.getId());
            List<UmsAdminRoleRelation> adminRoleRelations = iUmsAdminRoleRelationService.list(lqw1);

            List<String> roleName = new ArrayList<>();
            List<Long> roleIds = new ArrayList<>();
            for (UmsAdminRoleRelation adminRoleRelation : adminRoleRelations) {
                LambdaQueryWrapper<UmsRole> lqw2 = new LambdaQueryWrapper<>();
                lqw2.eq(UmsRole::getId, adminRoleRelation.getRoleId());
                UmsRole role = iUmsRoleService.getOne(lqw2);
                roleName.add(role.getName());
                roleIds.add(role.getId());
            }

            QueryWrapper<UmsRoleMenuRelation> lqw3 = new QueryWrapper<>();
            lqw3.select("DISTINCT menu_id").in("role_id",roleIds);
            List<UmsRoleMenuRelation> roleMenuRelations = iUmsRoleMenuRelationService.list(lqw3);
            List<Long> menuIds = new ArrayList<>();
            for (UmsRoleMenuRelation roleMenuRelation : roleMenuRelations) {
                menuIds.add(roleMenuRelation.getMenuId());
            }

            LambdaQueryWrapper<UmsMenu> lqw4 = new LambdaQueryWrapper<>();
            lqw4.in(UmsMenu::getId,menuIds);
            List<UmsMenu> menus = iUmsMenuService.list(lqw4);

            Map<String, Object> map = new HashMap<>();
            map.put(Constants.USERNAME, username);
            map.put(Constants.ICON, umsAdmin.getIcon());
            map.put(Constants.ROLES, roleName);
            map.put(Constants.MENUS,menus);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}
